package com.zj.docker.controller;

import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.exceptions.DockerException;
import com.spotify.docker.client.messages.Image;
import com.spotify.docker.client.messages.ImageInfo;
import com.zj.docker.client.UserClient;
import com.zj.docker.common.User;
import com.zj.docker.component.DockerComponent;
import com.zj.docker.component.LogComponent;
import com.zj.docker.component.UserRoleAuthentication;
import com.zj.docker.domain.ImagesInfo;
import com.zj.docker.enums.CommonEnum;
import com.zj.docker.enums.LogEnum;
import com.zj.docker.enums.RoleEnum;
import com.zj.docker.service.ImagesInfoService;
import com.zj.docker.utils.ListPagingUtils;
import com.zj.docker.utils.ResultVoUtil;
import com.zj.docker.vo.ResultVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Auther: zj
 * @Date: 2018/12/3 16:45
 * @Description: image
 */
@RestController
public class ImageController {

    @Autowired
    DockerComponent docker;
    @Autowired
    UserRoleAuthentication userRoleAuthentication;
    @Autowired
    ImagesInfoService imagesInfoService;
    @Autowired
    UserClient userClient;
    @Autowired
    LogComponent logComponent;


    @Value("${docker.Url}")
    private String dockerUrl; //docker的ip地址+端口号

    /**
     *  获取所有本地镜像（docker client）,需要管理员权限
     * 包含本地公共和本地用户镜像
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @GetMapping("/admin/list/all/images")
    public ResultVo<Object> ListAllImages(HttpServletRequest request) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<Image> quxImages = docker.getThisDockerClient().listImages( DockerClient.ListImagesParam.allImages() );
        return ResultVoUtil.success( quxImages.toString() );
    }

    /**
     * 列出所有的镜像（from data base）,需要管理员权限,分页
     * @param request
     * @return
     */
    @GetMapping("/admin/list/all/imagesFromMysql")
    public ResultVo listAllImagesFromMysql(HttpServletRequest request,
                                           @RequestParam("pageIndex") Integer pageIndex) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list = imagesInfoService.listAllImagesFromDataBase();
        List<Object> list_new=ListPagingUtils.getPaging( list,pageIndex-1,5 );
        return ResultVoUtil.success( list_new );
    }

    /**
     * 获取列出所有的镜像的总数（from data base）,需要管理员权限
     * @param request
     * @return
     */
    @GetMapping("/admin/list/all/imagesFromMysqlTotal")
    public ResultVo listAllImagesFromMysqlTotal(HttpServletRequest request) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list = imagesInfoService.listAllImagesFromDataBase();
        return ResultVoUtil.success( list.size());
    }

    /**
     * 获取镜像的详细信息，需要管理员权限
     * @param request
     * @param imageId
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @GetMapping("/admin/getDetailAboutImage")
    public ResultVo adminGetDetailAboutImage(HttpServletRequest request,
                                        @RequestParam("imageId") String imageId) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        ImageInfo imageInformation = docker.getThisDockerClient().inspectImage( imageId );
        return ResultVoUtil.success( imageInformation );
    }

//    /**
//     * 删除镜像，管理员权限
//     * @param request
//     * @param imageId
//     * @return
//     */
//    @GetMapping("/admin/remove/theImage")
//    public ResultVo adminRemoveTheImage1(HttpServletRequest request,
//                                        @RequestParam("imageId") String imageId) {
//        //鉴权
//        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
//        System.out.println( username );
//        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
//            return ResultVoUtil.error();
//        }
//        try {
//            docker.getThisDockerClient().removeImage( imageId );
//
//        } catch (DockerException | InterruptedException e) {
//            e.printStackTrace();
//            return ResultVoUtil.error(CommonEnum.ERROR_REMOVE_IMAGE.getMessage());
//        }
//        //同步数据库
//        imagesInfoService.deleteTheImage( imageId );
//
//        return ResultVoUtil.success();
//
//    }

    /**
     * 管理员，上传镜像    默认本地公共镜像，镜像默认公开
     * @param request
     * @param fullName
     * @param file
     * @param description
     * @param Instructions
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @PostMapping("/admin/import/newImage")
    public ResultVo AdminImportNewImage(HttpServletRequest request,
                                        @RequestParam("fullName") String fullName,
                                        @RequestParam("file") MultipartFile file,
                                        @RequestParam(value = "description",required=false,defaultValue ="") String description,
                                        @RequestParam(value = "Instructions",required=false,defaultValue = "") String Instructions) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        // 判断镜像名是否有大写字符
        for(int i=0; i<fullName.length(); i++) {
            if(Character.isUpperCase(fullName.charAt(i))){
                return ResultVoUtil.error(CommonEnum.IMAGE_NAME_CONTAIN_UPPER.getMessage());
            }
        }
        //确保fullname唯一
        if(imagesInfoService.findImagesInfoByFullName( fullName)!=null) {
            return ResultVoUtil.error(CommonEnum.IMAFEFULLNAMEISSAME.getMessage());
        }
        // 判断文件后缀
        if(!file.getOriginalFilename().endsWith(".tar")) {
            return ResultVoUtil.error(CommonEnum.IMAGE_UPLOAD_ERROR_BY_SUFFIX.getMessage());
        }
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        try {
            InputStream stream = file.getInputStream();
            //创建镜像,并同步数据库（异步）
            ImagesInfo image =imagesInfoService.createImageByImport( fullName,stream,description,Instructions,CommonEnum.IMAGETYPEPUBLIC.getCode(),
                    username,CommonEnum.IMAGEHASOPEN1.getCode(),date,date);
            if (image==null) {
                return ResultVoUtil.error(CommonEnum.ERROR10001.getMessage());
            }
            return ResultVoUtil.success("镜像开始导入");
        } catch (IOException e) {
            return ResultVoUtil.error(CommonEnum.ERROR_EXPECTION10002.getMessage());
        }
    }


    /**
     * 管理员权限(前提条件：已经生成image-id；上传公共镜像)，同步数据库
     * @param request
     * @param imageId
     * @param description
     * @param Instructions
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @PostMapping("/admin/insert/newImage")
    public ResultVo<Object> InsertNewImage(HttpServletRequest request, @RequestParam(value = "imageId") String imageId,
                                           @RequestParam(value = "description",required=false,defaultValue = "") String description,
                                           @RequestParam(value = "Instructions",required=false,defaultValue = "") String Instructions
                                           ) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        String fullName = null;
        ImageInfo imageInformation = docker.getThisDockerClient().inspectImage( imageId );

        List<Image> quxImages = docker.getThisDockerClient().listImages( DockerClient.ListImagesParam.allImages());
        for (Image quxImage : quxImages) {
            if(Objects.equals( quxImage.id(), imageInformation.id() )) {
                System.out.println( quxImage.repoTags().get( 0 ) );
                fullName = quxImage.repoTags().get( 0 );//获取repoTags
            }
        }
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        //同步数据库
        ImagesInfo image = imagesInfoService.createNewImage(imageId, fullName, null,null ,description,
                Instructions,imageInformation.size(),CommonEnum.IMAGETYPEPUBLIC.getCode(),
                CommonEnum.STATE_PUBLIC.getMessage(), CommonEnum.IMAGEHASOPEN1.getCode(),
                imageInformation.virtualSize(), null,null, date,date);
        return ResultVoUtil.success(image);
    }

    //管理员权限，删除指定镜像
    @GetMapping("/admin/remove/theImage")
    public ResultVo AdminRemoveTheImage(HttpServletRequest request,
                                        @RequestParam("imageId") String imageId) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.Admin.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        try {
            docker.getThisDockerClient().removeImage( imageId );
        } catch (DockerException | InterruptedException e) {
            e.printStackTrace();
            return ResultVoUtil.error(CommonEnum.ERROR_REMOVE_IMAGE.getMessage());
        }
        //同步数据库
        imagesInfoService.deleteTheImage( imageId );

        logComponent.saveLog( request, LogEnum.IMAGE_DELETE );

        return ResultVoUtil.success();

    }

    /**
     * 列出所有开放的镜像，普通用户权限
     * @param request
     * @return
     */
    @GetMapping("/getAllImagesHasOpen")
    public ResultVo getAllImagesHasOpen(HttpServletRequest request) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list =imagesInfoService.listImagesByHasOpen( 1 );

        return ResultVoUtil.success(list);
    }

    /**
     * 分页，显示所有开放的镜像，普通用户权限
     * @param request
     * @param pageIndex
     * @return
     */
    @GetMapping("/customer/getAllImagesHasOpenWithPage")
    public ResultVo getAllImagesHasOpenWithPage(HttpServletRequest request,
                                                @RequestParam(value = "pageIndex",required = false,defaultValue = "1") int pageIndex) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list = imagesInfoService.listImagesByHasOpenWithPage(1,pageIndex-1).getContent();
//        List<ImagesInfo> listAll =imagesInfoService.listImagesByHasOpen( 1 );

        return ResultVoUtil.success(list);
    }
    /**
     * 获取所有开放的镜像的总数，普通用户权限
     * @param request
     * @return
     */
    @GetMapping("/getTotalOfImagesHasOpen")
    public ResultVo getTotalOfImagesHasOpen(HttpServletRequest request) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> listAll =imagesInfoService.listImagesByHasOpen( 1 );

        return ResultVoUtil.success(listAll.size());
    }

    /**
     * 列出当前用户上传的所有镜像，普通用户权限
     * @param request
     * @return
     */
    @GetMapping("/getAllImagesFromSelf")
    public ResultVo getAllimagesFromSelf(HttpServletRequest request) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list = imagesInfoService.listSelfImages( username );
        return ResultVoUtil.success(list);
    }

    /**
     * 查看当前用户上传的所有镜像的数量，普通用户权限
     * @param request
     * @return
     */
    @GetMapping("/user/getSelfUploadImagesTotal")
    public ResultVo getSelfUploadImagesTotal(HttpServletRequest request) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        List<ImagesInfo> list = imagesInfoService.listSelfImages( username );
        return ResultVoUtil.success(list.size());
    }

    /**
     * 分页，查看当前用户上传的所有镜像，普通用户权限
     * @param request
     * @param pageIndex
     * @return
     */
    @GetMapping("/user/getSelfUploadImages")
    public ResultVo getSelfUploadImages(HttpServletRequest request,
                                        @RequestParam(value = "pageIndex",required = false,defaultValue = "1") Integer pageIndex) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }

        List<ImagesInfo> list = imagesInfoService.listSelfImagesWithPage( username,pageIndex-1 ).getContent();

        return ResultVoUtil.success(list);
    }

    /**
     *  获取image的详细信息，普通用户的权限
     * @param request
     * @param imageId
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @GetMapping("/getDetailAboutImage")
    public ResultVo getDetailAboutImage(HttpServletRequest request,
                                        @RequestParam("imageId") String imageId) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        ImageInfo imageInformation = docker.getThisDockerClient().inspectImage( imageId );
        return ResultVoUtil.success( imageInformation );
    }

    /**
     * 用户权限，导出镜像
     * @param request
     * @param fullName
     * @return
     */
    @GetMapping("/customer/downImage")
    public ResultVo downImage(HttpServletRequest request,
                              @RequestParam("fullName") String fullName) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }

        String imageDownUrl = dockerUrl+"/images/"+fullName+"/get";
        System.out.println( imageDownUrl );

        logComponent.saveLog( request,LogEnum.IMAGE_EXPORT );
        return ResultVoUtil.success(imageDownUrl);
    }

    /**
     * 私有镜像，切换状态,需要用户权限
     * @param request
     * @param fullName
     * @param state
     * @return
     */
    @GetMapping("/changeSelfImageState")
    public ResultVo changeSelfImageState(HttpServletRequest request,
                                         @RequestParam("fullName") String fullName,
                                         @RequestParam("state") String state) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }

        ImagesInfo imagesInfo = imagesInfoService.findImagesInfoByFullName( fullName );

        if (Objects.equals( state, "公开" )) {
            imagesInfo.setHasOpen( 0 );
        }
        if (Objects.equals( state,"私有" )) {
            imagesInfo.setHasOpen( 1 );
        }

        imagesInfoService.SaveOrUpdate( imagesInfo );

        logComponent.saveLog( request,LogEnum.IMAGE_CHANGE_STATUS );
        return ResultVoUtil.success();
    }



    /**
     * 导入镜像，普通用户权限
     * @param request
     * @param fullName
     * @param file
     * @param description
     * @param Instructions
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @PostMapping("/customer/import/newImage")
    public ResultVo customerImportNewImage(HttpServletRequest request,
                                        @RequestParam("fullName") String fullName,
                                        @RequestParam("file") MultipartFile file,
                                        @RequestParam(value = "description",required=false,defaultValue = "") String description,
                                        @RequestParam(value = "Instructions",required=false,defaultValue = "") String Instructions) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }

        if(fullName==null) {
            return ResultVoUtil.error("镜像名不能为空！");
        }
        //若用户未输入版本号 则默认最新的版本
        if (!fullName.contains(":")) {
            fullName = fullName + ":latest";
        }
        // 判断镜像名是否有大写字符
        for(int i=0; i<fullName.length(); i++) {
            if(Character.isUpperCase(fullName.charAt(i))){
                return ResultVoUtil.error(CommonEnum.IMAGE_NAME_CONTAIN_UPPER.getMessage());
            }
        }
        String newName = username+"/"+fullName;
        //确保fullname唯一
        if(imagesInfoService.findImagesInfoByFullName( newName)!=null) {
            return ResultVoUtil.error(CommonEnum.IMAFEFULLNAMEISSAME.getMessage());
        }

        // 判断文件后缀
        if(!file.getOriginalFilename().endsWith(".tar")) {
            return ResultVoUtil.error(CommonEnum.IMAGE_UPLOAD_ERROR_BY_SUFFIX.getMessage());
        }
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳
        try {
            InputStream stream = file.getInputStream();
            //创建镜像,并同步数据库（异步）
            ImagesInfo image =imagesInfoService.createImageByImport( newName,stream,description,Instructions,CommonEnum.IMAGETYPEPRIVATE.getCode(),
                    username,CommonEnum.IMAGEHASOPEN0.getCode(),date,date);

            return ResultVoUtil.success("镜像开始导入");
        } catch (IOException e) {
            return ResultVoUtil.error(CommonEnum.ERROR_EXPECTION10002.getMessage());
        }
    }

    //验证用户输入的镜像名，是否重名
    @GetMapping("/getImageFullNameIsOnlyOne")
    public ResultVo getImageFullNameIsOnlyOne(HttpServletRequest request,
                                              @RequestParam("fullName") String fullName) {

        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }

        String newName = username+"/"+fullName;

        ImagesInfo image = imagesInfoService.findImagesInfoByFullName( newName );

        if (image!=null) {//镜像名重名
            return ResultVoUtil.error("该镜像名已存在");
        }

        return ResultVoUtil.success();
    }

    //删除镜像，普通用户权限
    @GetMapping("/customer/remove/theImage")
    public ResultVo CustomerRemoveTheImage(HttpServletRequest request,
                                        @RequestParam("imageId") String imageId) {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        try {
            docker.getThisDockerClient().removeImage( imageId );
        } catch (DockerException | InterruptedException e) {
            e.printStackTrace();
            return ResultVoUtil.error(CommonEnum.ERROR_REMOVE_IMAGE.getMessage());
        }
        //同步数据库
        imagesInfoService.deleteTheImage( imageId );
        logComponent.saveLog( request,LogEnum.IMAGE_DELETE );
        return ResultVoUtil.success();

    }

    /**
     * pull 镜像 从docker hub上 普通用户权限
     * @param request
     * @param fullName
     * @return
     * @throws DockerException
     * @throws InterruptedException
     */
    @GetMapping("/customer/imagePull")
    public ResultVo imagePull(HttpServletRequest request,
                              @RequestParam("fullName") String fullName) throws DockerException, InterruptedException {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        if(StringUtils.isBlank(fullName)) {
            return ResultVoUtil.error(CommonEnum.PARAM_ERROR.getMessage());
        }
        //若用户未输入版本号 则默认pull最新的版本
        if (!fullName.contains(":")) {
            fullName = fullName + ":latest";
        }
        if (docker.getThisDockerClient().listImages( DockerClient.ListImagesParam.byName( fullName ) ).size() > 0) {
            return ResultVoUtil.error(CommonEnum.IMAGE_HAS_EXEIST.getMessage());
        }

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        String date = df.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳

        User user = userClient.getUserByUsername( username );
        String sessionId =user.getWebsocketSessionId();

        //异步
        imagesInfoService.imagePull( fullName,sessionId,date );

        return ResultVoUtil.success("开始拉取镜像");
    }


}


